/*
 * @Author: 0x9DEFA478
 * @Date: 2025-06-28 14:34:44
 * @LastEditTime: 2025-08-17 23:39:05
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * 
 */
#include "hmkdecode.hpp"
#include <vector>
#include <fstream>
#include <stdexcept>
#include "Container/H_Stack.hpp"

#include "SystemUtility/C_iostream.hpp"


static std::string MakeErrorString(const std::string& path,int line,int pos,const std::string& reason){
  return path+":"+std::to_string(line)+":"+std::to_string(pos)+" "+reason;
}


namespace HMake{


  const char* HMK_Element::TypeToString(Type type){
    switch(type){
      case Type::Text:return "Text";break;
      case Type::ValueMark:return "ValueMark";break;
      case Type::BracketBegin:return "BracketBegin";break;
      case Type::BracketEnd:return "BracketEnd";break;
      case Type::Comma:return "Comma";break;
      case Type::String:return "String";break;
      case Type::NewLine:return "NewLine";break;
      case Type::Equal:return "Equal";break;
      case Type::EqualSelfAdd:return "EqualSelfAdd";break;
      case Type::EqualSelfSub:return "EqualSelfSub";break;
      case Type::Add:return "Add";break;
      case Type::Sub:return "Sub";break;
      default:
        break;
    }
    return "<unknow type>";
  }

  std::vector<HMK_Element::Pointer> HMK_Element::decode(const std::string& path){
    std::vector<Pointer> r;
    std::ifstream file;
    int line;

    file.open(path,std::ios::in);

    if(!file.is_open()){
      throw std::runtime_error("无法打开\""+path+"\"");
    }

    line=1;

    while(!file.eof()){
      std::string linestr;
      std::getline(file,linestr);

      std::size_t length=linestr.length();
      std::size_t index=0;

      while((length>0)&&((linestr[length-1]=='\r')||(linestr[length-1]=='\n'))){
        length--;
      }

      while(index<length){
        char c;

        c=linestr[index];

        if(c==' '){
          index++;
          continue;
        }
        
        switch(c){
          case '\"':
            {
              std::stringstream ss;
              bool IsFindEnd=false;

              index++;
              int BeginIndex=index;

              while(index<length){
                char c;

                c=linestr[index];

                if(c=='\"'){
                  IsFindEnd=true;
                  break;
                }

                if(c=='\\'){
                  index++;
                  if(index>=length){
                    throw std::runtime_error(MakeErrorString(path,line,index,"不完整的字符串"));
                  }

                  c=linestr[index];

                  switch(c){
                    case 'r':c='\r';break;
                    case 'n':c='\n';break;
                    case 't':c='\t';break;
                    case '0':c='\0';break;
                    case 'e':c='\e';break;
                    default:
                      break;
                  }
                }

                index++;
                ss<<c;
              }

              if(!IsFindEnd){
                throw std::runtime_error(MakeErrorString(path,line,index+1,"字符串没有有效的结尾'\"'"));
              }

              r.emplace_back(Pointer(new HMK_Element_String(ss.str(),line,BeginIndex+1)));
            }
            break;
          case ',':
            r.emplace_back(Pointer(new HMK_Element(Type::Comma,line,index+1)));
            break;
          case ':':
            r.emplace_back(Pointer(new HMK_Element(Type::Colon,line,index+1)));
            break;
          case '$':
            r.emplace_back(Pointer(new HMK_Element(Type::ValueMark,line,index+1)));
            break;
          case '(':
            r.emplace_back(Pointer(new HMK_Element(Type::BracketBegin,line,index+1)));
            break;
          case ')':
            r.emplace_back(Pointer(new HMK_Element(Type::BracketEnd,line,index+1)));
            break;
          case '=':
            r.emplace_back(Pointer(new HMK_Element(Type::Equal,line,index+1)));
            break;
          case '+':
            if(((index+1)<length)&&(linestr[index+1]=='=')){
              r.emplace_back(Pointer(new HMK_Element(Type::EqualSelfAdd,line,index+1)));
              index++;
            }else{
              r.emplace_back(Pointer(new HMK_Element(Type::Add,line,index+1)));
            }
            break;
          case '-':
            if(((index+1)<length)&&(linestr[index+1]=='=')){
              r.emplace_back(Pointer(new HMK_Element(Type::EqualSelfSub,line,index+1)));
              index++;
            }else{
              r.emplace_back(Pointer(new HMK_Element(Type::Sub,line,index+1)));
            }
            break;
          case '#':
            index=length-1;//注释
            break;
          default://text
            if((r.size()>0)&&(r.back()->type_==Type::Text)){
              *static_cast<HMK_Element_Text*>(r.back().GetPointer())<<c;
            }else{
              r.emplace_back(Pointer(&((*new HMK_Element_Text(line,index+1))<<c)));
            }
            break;
        }

        index++;
      }
      
      if((r.size()>0)&&(r.back()->type_!=Type::NewLine)){
        r.emplace_back(Pointer(new HMK_Element(Type::NewLine,line,index+1)));
      }
      line++;
    }

    file.close();

    return r;
  }


  const char* Expression::TypeToString(Type type){
    switch(type){
      case Type::Collection:return "Collection";break;
      case Type::Text:return "Text";break;
      case Type::ValueMark:return "ValueMark";break;
      case Type::String:return "String";break;
      case Type::Assignment:return "Assignment";break;
      case Type::Arithmetic:return "Arithmetic";break;
      default:
        break;
    }
    return "<unknow type>";
  }

  //将hmk文件解析成多个集合
  std::vector<Expression::Pointer> Expression::decode(const std::string& path,const std::vector<HMK_Element::Pointer>& element){
    std::vector<Pointer> r;
    std::size_t Length;
    std::size_t BeginIndex;
    std::size_t Index;

    Length=element.size();
    BeginIndex=0;
    Index=0;
    while(Index<Length){
      if(element[Index]->type()!=HMK_Element::Type::NewLine){
        Index++;
        continue;
      }

      if(BeginIndex!=Index){
        r.emplace_back(decodeExpression(path,element,BeginIndex,Index));
      }

      Index++;
      BeginIndex=Index;
    }

    return r;
  }

  //完成括号结构 
  Expression::Pointer Expression::decodeExpression(const std::string& path,const std::vector<HMK_Element::Pointer>& expression,std::size_t sIndex,std::size_t eIndex){
    H::Stack<Pointer> stack;
    Pointer resCollection;

    resCollection=Pointer(new Expression_Collection(' ',expression[sIndex]->line(),expression[sIndex]->pos()));

    auto addElement=[](Pointer& pointer,Expression* element)->Pointer {
      auto r=Pointer(element);
      pointer->ToType<Expression_Collection>()->AddElement(r);
      return r;
    };

    while(sIndex<eIndex){
      
      switch(expression[sIndex]->type()){
        case HMK_Element::Type::BracketBegin:
          stack.Push(resCollection);
          resCollection=addElement(resCollection,new Expression_Collection('(',expression[sIndex]->line(),expression[sIndex]->pos()));
          break;
        case HMK_Element::Type::BracketEnd:
          {
            char BeginChar;
            if(stack.Empty()){
              throw std::runtime_error(MakeErrorString(path,expression[sIndex]->line(),expression[sIndex]->pos(),"意外的字符 ')'"));
            }
            BeginChar=resCollection->ToType<Expression_Collection>()->BeginChar();
            if(BeginChar!='('){
              throw std::runtime_error(MakeErrorString(path,resCollection->line(),resCollection->pos(),"'(' 没有合适的 ')' 来匹配, 在此之前可能需要字符来匹配'"+ std::string(1,BeginChar) +"'"));
            }
            resCollection=stack.Top();
            stack.Pop();
          }
          break;
        case HMK_Element::Type::ValueMark:
          addElement(resCollection,new Expression(Type::ValueMark,expression[sIndex]->line(),expression[sIndex]->pos()));
          break;
        case HMK_Element::Type::Comma:
          addElement(resCollection,new Expression_Operator(Type::Arithmetic,expression[sIndex]->line(),expression[sIndex]->pos(),','));
          break;
        case HMK_Element::Type::Colon:
          addElement(resCollection,new Expression_Operator(Type::Arithmetic,expression[sIndex]->line(),expression[sIndex]->pos(),':'));
          break;
        case HMK_Element::Type::Equal:
          addElement(resCollection,new Expression_Operator(Type::Assignment,expression[sIndex]->line(),expression[sIndex]->pos(),'='));
          break;
        case HMK_Element::Type::EqualSelfAdd:
          addElement(resCollection,new Expression_Operator(Type::Assignment,expression[sIndex]->line(),expression[sIndex]->pos(),'+'));
          break;
        case HMK_Element::Type::EqualSelfSub:
          addElement(resCollection,new Expression_Operator(Type::Assignment,expression[sIndex]->line(),expression[sIndex]->pos(),'-'));
          break;
        case HMK_Element::Type::Add:
          addElement(resCollection,new Expression_Operator(Type::Arithmetic,expression[sIndex]->line(),expression[sIndex]->pos(),'+'));
          break;
        case HMK_Element::Type::Sub:
          addElement(resCollection,new Expression_Operator(Type::Arithmetic,expression[sIndex]->line(),expression[sIndex]->pos(),'-'));
          break;
        case HMK_Element::Type::String:
          addElement(resCollection,new Expression_String(static_cast<const HMK_Element_String*>(expression[sIndex].GetPointer())));
          break;
        case HMK_Element::Type::Text:
          addElement(resCollection,new Expression_Text(static_cast<const HMK_Element_Text*>(expression[sIndex].GetPointer())));
          break;
        default:
          break;
      }

      sIndex++;
    }

    if(!stack.Empty()){
      throw std::runtime_error(MakeErrorString(path,resCollection->line(),resCollection->pos(),"'(' 没有合适的 ')' 来匹配"));
    }

    decodeOperator(path,resCollection);
    decodePriority(path,resCollection);

    return resCollection;
  }

  //根据运算符进一步处理 使运算符之间的非运算符对象集中成集合
  void Expression::decodeOperator(const std::string& path,Pointer& Expression){
    struct StackItem{
      Pointer pointer;
      Expression_Collection* Collection;
      Pointer new_pointer;
      std::vector<Pointer> tempArray;
      std::size_t Index;
      std::size_t Length;

      StackItem():Collection(nullptr),Index(0),Length(0){
      }
      StackItem(Pointer& pointer):pointer(pointer),Collection(pointer->ToType<Expression_Collection>()),Index(0),Length(Collection->Colloection().size()){
        new_pointer=Pointer(new Expression_Collection(Collection->BeginChar(),Collection->line(),Collection->pos()));
      }
    };
    H::Stack<StackItem> stack;
    StackItem currentStatus;

    if(Expression->type()!=Type::Collection){
      return;
    }

    currentStatus=StackItem(Expression);

    auto addElement=[](Pointer& pointer,Pointer& element){
      pointer->ToType<Expression_Collection>()->AddElement(element);
    };

    auto addElementArray=[](Pointer& pointer,std::vector<Pointer>& pointerArray){
      if(!pointerArray.empty()){
        
        if(pointerArray.size()<2){
          pointer->ToType<Expression_Collection>()->AddElement(pointerArray[0]);
        }else{
          Expression_Collection* Collection;
          
          Collection=new Expression_Collection(' ',pointerArray[0]->line(),pointerArray[0]->pos());
          for(auto& Item:pointerArray){
            Collection->AddElement(Item);
          }
          pointer->ToType<Expression_Collection>()->AddElement(Pointer(Collection));
        }

        pointerArray.clear();
      }
    };

    for(;;){
      
      while(currentStatus.Index<currentStatus.Length){
        auto item=currentStatus.Collection->Colloection()[currentStatus.Index];
        
        currentStatus.Index++;

        //处理子集合 子集合处理完成后, 会添加新的子集合到新集合中
        if(item->type()==Type::Collection){
          stack.Push(currentStatus);
          currentStatus=StackItem(item);
          continue;
        }

        //运算符直接添加
        if(item->IsOper()){
          addElementArray(currentStatus.new_pointer,currentStatus.tempArray);
          addElement(currentStatus.new_pointer,item);
          continue;
        }

        currentStatus.tempArray.emplace_back(item);

      }

      //添加剩余的临时列表到新集合
      addElementArray(currentStatus.new_pointer,currentStatus.tempArray);
      
      if(stack.Empty()){
        break;
      }else{
        //添加新的子集合到父级的临时集合
        stack.Top().tempArray.emplace_back(currentStatus.new_pointer);
      }

      currentStatus=stack.Top();
      stack.Pop();
    }

    Expression=currentStatus.new_pointer;
  }

  //根据运算优先级进一步处理 使得一个集合最多只有1个运算符
  void Expression::decodePriority(const std::string& path,Pointer& Expression){
    struct StackItem{
      Pointer pointer;
      Expression_Collection* Collection;
      std::vector<Pointer> new_Collection;
      bool IsOrder;
      std::size_t Index;
      std::size_t Length;

      StackItem():Collection(nullptr),IsOrder(false),Index(0),Length(0){
      }
      StackItem(Pointer& pointer):pointer(pointer),Collection(pointer->ToType<Expression_Collection>()),IsOrder(false),Index(0),Length(Collection->Colloection().size()){}
    };
    H::Stack<StackItem> stack;
    StackItem currentStatus;

    if(Expression->type()!=Type::Collection){
      return;
    }

    currentStatus=StackItem(Expression);

    for(;;){
      
      for(;;){
        if(!currentStatus.IsOrder){
          //排序 在这里一次性完成本级的排序 子集合的排序在后面递归进行

          std::vector<Pointer> Array;

          Array=currentStatus.Collection->Colloection();


          for(;;){
            std::size_t OperatorCount;
            std::size_t Length;
            std::size_t MaxPriorityIndex;
            int32_t MaxPriority;

            Length=Array.size();
            
            MaxPriorityIndex=Length;
            MaxPriority=INT32_MAX;
            OperatorCount=0;
            for(std::size_t i=0;i<Length;i++){
              if(Array[i]->IsOper()){
                auto Priority=Array[i]->ToType<Expression_Operator>()->Priority();
                OperatorCount++;
                if(MaxPriority>Priority){
                  MaxPriority=Priority;
                  MaxPriorityIndex=i;
                }
              }
            }
            if(OperatorCount<2){
              //已经不需要进行分级
              break;
            }

            std::vector<Pointer> newArray;
            newArray.reserve(Length);

            // auto oper=Array[MaxPriorityIndex]->ToType<Expression_Operator>();

            //不同操作数数量的运算符在这里进行不同的处理
            // if(oper->Operator()==','){
              auto nc=new Expression_Collection(' ',Array[MaxPriorityIndex]->line(),Array[MaxPriorityIndex]->line());

              if(MaxPriorityIndex>0){
                std::size_t length;

                length=MaxPriorityIndex-1;
                if(Array[MaxPriorityIndex-1]->IsOper()){
                  length=MaxPriorityIndex;
                }else{
                  nc->AddElement(Array[MaxPriorityIndex-1]);
                }
                for(std::size_t i=0;i<length;i++){
                  newArray.emplace_back(Array[i]);
                }
              }
              
              nc->AddElement(Array[MaxPriorityIndex]);
              newArray.emplace_back(Pointer(nc));

              if(MaxPriorityIndex<(Length-1)){
                std::size_t begin;

                begin=MaxPriorityIndex+2;
                if(Array[MaxPriorityIndex+1]->IsOper()){
                  begin=MaxPriorityIndex+1;
                }else{
                  nc->AddElement(Array[MaxPriorityIndex+1]);
                }
                for(std::size_t i=begin;i<Length;i++){
                  newArray.emplace_back(Array[i]);
                }
              }

            // }else{
            //   //2操作运算符处理

            //   if(MaxPriorityIndex>=Length){
            //     throw std::logic_error(MakeErrorString(path,Array[0]->line(),Array[0]->pos(),"内部错误: 该表达式被错误解析"));
            //   }
            //   if((MaxPriorityIndex<1)||(MaxPriorityIndex==(Length-1))){
            //     throw std::runtime_error(MakeErrorString(path,oper->line(),oper->pos(),"该运算符需要两个操作数"));
            //   }

            //   auto type=Array[MaxPriorityIndex-1]->type();
            //   if((type>=Type::OperatorStartIndex_)&&(type<Type::OperatorEnd_)){
            //     throw std::runtime_error(MakeErrorString(path,Array[MaxPriorityIndex-1]->line(),Array[MaxPriorityIndex-1]->pos(),"与后方的操作符冲突"));
            //   }
            //   type=Array[MaxPriorityIndex+1]->type();
            //   if((type>=Type::OperatorStartIndex_)&&(type<Type::OperatorEnd_)){
            //     throw std::runtime_error(MakeErrorString(path,oper->line(),oper->pos(),"与后方的操作符冲突"));
            //   }

            //   auto nc=new HMK_Element1_Collection(' ',Array[MaxPriorityIndex-1]->line(),Array[MaxPriorityIndex-1]->line());

            //   nc->AddElement(Array[MaxPriorityIndex-1]);
            //   nc->AddElement(Array[MaxPriorityIndex]);
            //   nc->AddElement(Array[MaxPriorityIndex+1]);

            //   for(std::size_t i=0,length=MaxPriorityIndex-1;i<length;i++){
            //     newArray.emplace_back(Array[i]);
            //   }
            //   newArray.emplace_back(Pointer(nc));
            //   for(std::size_t i=MaxPriorityIndex+2;i<Length;i++){
            //     newArray.emplace_back(Array[i]);
            //   }

            // }

            Array=newArray;
          }
          currentStatus.new_Collection=Array;
          currentStatus.IsOrder=true;
        }

        bool IsBreak=true;
        while(currentStatus.Index<currentStatus.Length){
          auto item=currentStatus.Collection->Colloection()[currentStatus.Index];
          auto type=item->type();
          
          currentStatus.Index++;

          //处理子集合
          if(type==Type::Collection){
            stack.Push(currentStatus);
            currentStatus=StackItem(item);
            IsBreak=false;
            break;
          }

        }
        if(IsBreak){
          break;
        }
      }

      //更新顺序
      currentStatus.Collection->Colloection()=currentStatus.new_Collection;
      
      if(stack.Empty()){
        break;
      }
      currentStatus=stack.Top();
      stack.Pop();
    }

  }

  int32_t Expression_Operator::Priority()const{
    switch(type()){
      case Type::Assignment:
        return 1;
      case Type::Arithmetic:
        switch(operator_){
          case ',':
            return 0;
          case ':':
            return -1;
          default:
            return -2;
        }
        break;
      default:
        break;
    }
    throw std::invalid_argument(std::string("无法提取优先级的类型:")+TypeToString(type()));
  }


  std::ostream& operator<<(std::ostream& ostream,HMK_Element::Type type){
    return ostream<<HMK_Element::TypeToString(type);
  }


}

#if 0
static void PrintfCollection(const HMake::Expression_Collection* Collection){
  std::string info="";

  if(Collection->BeginChar()==' '){
    H::cout<<'[';
  }else{
    H::cout<<Collection->BeginChar();
  }


  for(auto& Item:Collection->Colloection()){
    
    H::cout<<" "<<HMake::Expression::TypeToString(Item->type());

    switch(Item->type()){
      case HMake::Expression::Type::Text:
        H::cout<<":"<<Item->ToType<HMake::Expression_Text>()->Text();
        break;
      case HMake::Expression::Type::String:
        H::cout<<":"<<Item->ToType<HMake::Expression_String>()->str();
        break;
      case HMake::Expression::Type::Collection:
        PrintfCollection(Item->ToType<HMake::Expression_Collection>());
        break;
      case HMake::Expression::Type::Assignment:
        H::cout<<":"<<Item->ToType<HMake::Expression_Operator>()->Operator();
        if(Item->ToType<HMake::Expression_Operator>()->Operator()!='='){
          H::cout<<"=";
        }
        break;
      case HMake::Expression::Type::Arithmetic:
        H::cout<<":"<<Item->ToType<HMake::Expression_Operator>()->Operator();
        break;
      default:
        break;
    }

  }

  if(Collection->BeginChar()=='('){
    H::cout<<")";
  }else if(Collection->BeginChar()==' '){
    H::cout<<']';
  }
}

void Debug_Call(const std::string& path){

  // try{
  //   auto ea=HMake::HMK_Element0::decode(path);

  //   for(auto& Item:ea){
  //     std::string info="";

  //     info+=HMake::HMK_Element0::TypeToString(Item->type());

  //     switch(Item->type()){
  //       case HMake::HMK_Element0::Type::Text:
  //         info+=" "+static_cast<HMake::HMK_Element0_Text*>(Item.GetPointer())->Text();
  //         break;
  //       case HMake::HMK_Element0::Type::String:
  //         info+=" "+static_cast<HMake::HMK_Element0_String*>(Item.GetPointer())->str();
  //         break;
  //       default:
  //         break;
  //     }

  //     H::cout<<info<<std::endl;
  //   }
  // }catch(const std::exception& e){
  //   H::cout<<e.what()<<std::endl;
  // }

  try{
    auto ea=HMake::Expression::decode(path,HMake::HMK_Element::decode(path));

    for(auto& Item:ea){
      if(Item->type()!=HMake::Expression::Type::Collection){
        throw std::runtime_error(MakeErrorString(path,Item->line(),Item->pos(),"意外的根类型:"+std::string(HMake::Expression::TypeToString(Item->type()))));
      }
      
      H::cout<<"line:"<<Item->line()<<"  ";
      PrintfCollection(Item->ToType<HMake::Expression_Collection>());
      H::cout<<std::endl;
    }
  }catch(const std::exception& e){
    H::cout<<e.what()<<std::endl;
  }
}
#endif
